import React, {
    useContext, useEffect, useRef, forwardRef
} from 'react';

// 解决一下跟根组件不能使用装饰器的问题
function getRef(ref, ref2) {
    if (typeof ref === 'function') {
        const fnRef = (instance, ...args) => {
            // 给function添加current属性，用来模拟createRef()
            fnRef.current = instance;
            ref(instance, ...args);
        };
        return fnRef;
    }
    if (ref && ref.current) {
        return ref;
    }
    return ref2;
}

/**
 * 用来获取page Context
 * @export
 * @returns
 */
export function usePageContext() {
    return useContext('');
}

/**
 * 通过context共享页面基础数据
 * 此高阶组件会把传入组件的实例push到$dom元素的showHideList，从而实现监听onPageShow/onPageHide/onWechatShare事件
 * 还会向组件内注入context props，以方便组件获取当前页面的query/params/router等参数
 * @export
 * @param {React.Component} Comp
 * @returns {React.Component}
 */
export default function showHide(Comp) {
    function SelectContext(props, ref) {
        const realRef = getRef(ref, useRef());
        const context = usePageContext();

        useEffect(() => {
            const { $dom } = context;
            const instance = realRef.current;
            $dom.showHideList = $dom.showHideList || [];
            $dom.showHideList.push(instance);
            return () => {
                $dom.showHideList = $dom.showHideList.filter(is => is !== instance);
            };
        }, []);

        return <Comp {...props} context={context} ref={realRef} />;
    }

    SelectContext.displayName = 'SelectContext';

    return forwardRef(SelectContext);
}

const addEventListener = (instance, context) => () => {
    const { $dom } = context;
    $dom.showHideList = $dom.showHideList || [];
    $dom.showHideList.push(instance);
    return () => {
        $dom.showHideList = $dom.showHideList.filter(is => is !== instance);
    };
};

/**
 * 监听页面显示
 * @export
 * @param {function} onPageShow
 */
export function usePageShow(pageShowFn, option) {
    const context = usePageContext();
    const ref = useRef();
    useEffect(() => {
        ref.current = pageShowFn;
    }, [pageShowFn]);

    const effect = addEventListener(
        {
            onPageShow() {
                ref.current && ref.current();
            },
            ...option,
        },
        context
    );

    useEffect(effect, []);
}

/**
 * 监听页面隐藏
 * @export
 * @param {function} onPageHide
 */
export function usePageHide(pageHideFn, option) {
    const context = usePageContext();
    const ref = useRef();
    useEffect(() => {
        ref.current = pageHideFn;
    }, [pageHideFn]);

    const effect = addEventListener(
        {
            onPageHide() {
                ref.current && ref.current();
            },
            ...option,
        },
        context
    );

    useEffect(effect, []);
}
